
/*
class DfsVisitor {
public:
	virtual ~DfsVisitor() { }
	virtual void coneToVErtex(int vertex) = 0 {}
	virtual void leaveVertex(int vertex) = 0 {}
	virtual void processEdge(int fromVertex, int toVertex) = 0 {}
};

void DFS(const Graph& graph,int Start DfsVisitor& visitor);

struct TopologicalSortVisitor : public DfsVisitor {
	void comeToVertex(int vertex)
	{
		greyVertices
	}

	void leaveVertex(int vertex)
	{
		vertexOrder_.pus
	}

	void ProcessEdge(int fromVertex, int toVertex)
	{
		if (greyVertices.count(toVertex) > 0) {
			throw std::runtime_error("Graph has a loop");
		}
	}

	struct TarjanVisitor : public DfsVisitor {
		void comeToVertex(int vertex);

	}*/

	

    class DfsVisitor {
    public:
            virtual ~DfsVisitor() {};
            virtual void comeToVertex(int Vertex) = 0;
            virtual void leaveVertex(int Vertex) = 0;
            virtual void processEdge(int fromVertex, int toVertex) = 0;
    };
     
    void DFS(const Graph& graph, DfsVisitor& visitor) {
          
    }
     
    struct TopologicalSortVisitor : public DfsVisitor {
            void comeToVertex(int vertex) {
                    greyVertices_.insert(vertex);
            }
           
            void leaveVertex(int vertex) {
                    vertexOrder_.push_back(vertex);
                    greyVertices_.erase(vertex);
            }
           
            void processEdge(int fromVertex, int toVertex) {
                    if (greyVertices_.count(toVertex) > 0) {
                            throw runtime_error("Graho has s loop!");
                    }
            }
           
            set<int> greyVertices_;
            deque<int> vertexOrder_;
    };
     
    struct FindPathVisitor : public DfsVisitor {
            void processEdge(int fromVertex, int toVertex) {
                    parent_.insert(make_pair(fromVertex, toVertex));
            }
           
            vector<int> getPath();
    };
     
struct TarjanVisitor : public DfsVisitor {
	std::map<int, int> timeIn_;
	std::set<int> lowestTime_;
	std::set<int>isVisited_;
	std::stack<int> storedVertexes_;
	int timer = 0;

    void comeToVertex(int vertex) 
	{
		storedVertexes_.push(vertex);
		timeIn_[vertex] = timer;
		lowestTime_[vertex] = timer++;
		isVisited_.insert(vertex);
    }
           
    void leaveVertex(int vertex)
	{  

    }
           
    void processEdge(int fromVertex, int toVertex)
	{ 
		if(isVisited_.count(toVertex)){
			lowestTime_[fromVertex] = min(lowestTime_[fromVertex], lowestTime[toVertex]);
		}
    }
           

    };

